# --------------------------------------------------------------------------------------------------------------------
# Project:             Digital Payment System (DPS)
# Website:             http://code.google.com/p/dps-x509/
# Purpose of document: This is the main entry point into the registar web site
# --------------------------------------------------------------------------------------------------------------------
from google.appengine.ext import db
import sys
import string

try:
  import simplejson as json
except ImportError:
  import json
  
import dps.utils
import dps.x509AttributeAndValue
import dps.x509Certificate
import dps.x509CertificateParams
import dps.x509Helper      
      
import model

# --------------------------------------------------------------------------------------------------------------------
class CertificateChain:
  """ Builds a certificate chain from a leaf certficate """
  
# --------------------------------------------------------------------------------------------------------------------
  def __getDbCertificateChain(self, dbCert):
    """ Build chain orderd from original issuer certificate to leaf """
    if not dbCert:
      return []
    
    return self.__getDbCertificateChain(dbCert.issuerCertificate_) + [dbCert]

# --------------------------------------------------------------------------------------------------------------------
  def __findTokenCertificate(self):
    """ Look for token in certificate chain """
    dps.utils.assertion(self.chain_ and len(self.chain_) > 0, "Chain must be > 0 certs")
    for cert in self.chain_:
      if cert.isTokenCertificate_:
        return cert
    return None

# --------------------------------------------------------------------------------------------------------------------
  def __doesTextAppearInName(self, matchText, nameList):
    """ Searches for matchText in nameList"""
    dps.utils.assertion(isinstance(nameList, dps.x509AttributeAndValue.X509AttributeAndValueList), \
                        "CertificateChain.__doesTextAppearInName: Invalid nameList")
    if matchText == "":
      return False
    
    for item in nameList.list_:
      if item.getValue() == matchText:
        return True
        
    return False
  
# --------------------------------------------------------------------------------------------------------------------
  def __init__(self, dbCert):
    """ constructor """
    dps.utils.assertion(dbCert, "Certificate must be in the database")
    self.chain_ = self.__getDbCertificateChain(dbCert)
    self.tokenCert_ = self.__findTokenCertificate()
    dps.utils.assertion(self.tokenCert_, "Token certificate must exist")
      
# --------------------------------------------------------------------------------------------------------------------
  def isCertificateInChain(self, certBase64):
    """ look for certificate in the certificate chain """
    for cert in self.chain_:
      if cert.base64RawCertificate_ == certBase64:
        return True
    return False
    
# --------------------------------------------------------------------------------------------------------------------
  def doParamsMatchChain(self, params):
    """ Compare params against certificate chain. """
    if not params or params == { "tokenType": "", "tokenQuantity": "", "issuer": "", "subject": "", "redeemer": "" }:
      return True
    tokenQuantity = str("%.2f" % (1.0 * self.tokenCert_.tokenQuantity_ / 100))
    cert = dps.x509Certificate.X509Certificate.load(self.tokenCert_.base64RawCertificate_)    
    ret = self.tokenCert_.tokenType_ == params["tokenType"] or \
          tokenQuantity == params["tokenQuantity"] or \
          self.__doesTextAppearInName(params["issuer"], cert.getParams().getIssuer()) or \
          self.__doesTextAppearInName(params["subject"], cert.getParams().getSubject()) or \
          self.tokenCert_.redeemer_ == params["redeemer"]
    if not ret:
      for cert in self.chain_:
        cert = dps.x509Certificate.X509Certificate.load(self.tokenCert_.base64RawCertificate_)    
        if self.__doesTextAppearInName(params["issuer"], cert.getParams().getIssuer()) or \
           self.__doesTextAppearInName(params["subject"], cert.getParams().getSubject()):
          ret = True
          break
    return ret

# --------------------------------------------------------------------------------------------------------------------
  def getCertificateChain(self):
    """ from newest to oldest """
    l = []
    for cert in self.chain_:
      l.append(cert.base64RawCertificate_)
    l.reverse()
    return dps.x509Helper.prettyBase64Certificates(l)

# --------------------------------------------------------------------------------------------------------------------
  def getTokenHtmlRows(self, indentPixels=20):
    """ get html table representation. Each level is indented indentPixels. """
    rowData = ""

    for i in range(0, len(self.chain_)):      
      cert = self.chain_[i]
      issuerShading = ""
      if not cert.isTokenCertificate_:
        issuerShading = " bgcolor='#CBFCBF'"

      if i == 0:
        rowSpanText = " rowspan='%s'" % len(self.chain_)
        dps.utils.out(str(self.tokenCert_))
        rowData += """<tr><td%s><table>
                    <tr><td>Token Quantity:</td><td>%.2f</td></tr>
                    <tr><td>Token Type:</td><td>%s</td></tr>
                    <tr><td>Redeemer:</td><td>%s</td></tr>
                    <tr><td>Exchanger:</td><td>%s</td></tr>
                    </table></td><td valign='top' %s>%s</td><td%s>%s</td><td%s>%s</td>
                   <td%s><a href='/registrar/detail?id=%s'>detail</a></td></tr>""" % \
                   (rowSpanText, 1.0 * self.tokenCert_.tokenQuantity_ / 100, self.tokenCert_.tokenType_,
                    self.tokenCert_.redeemer_, dps.utils.stringify(self.tokenCert_.exchanger_, "&nbsp;"), rowSpanText, 
                    self.tokenCert_.issuer_, issuerShading, self.tokenCert_.registrationDate_, issuerShading, 
                    cert.subject_, issuerShading, self.tokenCert_.key())
      else:
        rowData += """<tr%s valign='top'><td>%s</td><td style='padding-left:%d' valign='top'>%s</td>
                    <td><a href='/registrar/detail?id=%s'>detail</a></td></tr>""" % \
                   (issuerShading, dps.utils.stringify(cert.registrationDate_, "&nbsp;"), i * indentPixels, 
                    cert.subject_, cert.key())
    return rowData

# --------------------------------------------------------------------------------------------------------------------
  def getJsonRepresentation(self):
    """ get JSON fromat suitable for web services. """
    ret = {"tokenQuantity"    : str("%.2f" %(1.0 * self.tokenCert_.tokenQuantity_ / 100)),
           "tokenType"        : self.tokenCert_.tokenType_,
           "redeemer"         : self.tokenCert_.redeemer_,
           "exchanger"        : dps.utils.stringify(self.tokenCert_.exchanger_),
           "registrar"        : self.tokenCert_.registrar_,
           "certificateChain" : self.getCertificateChain() }
    return ret
    
      